package org.breizhjug.cxf2jmeter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class CxfReader
{
    private File file;

    private DocumentBuilder builder;

    public CxfReader( File file )
        throws ParserConfigurationException
    {
        this.file = file;

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        builder = factory.newDocumentBuilder();
    }

    public List<Message> readMessages()
        throws FileNotFoundException, IOException, SAXException
    {
        List<Message> messages = new ArrayList<Message>();

        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        try
        {
            Message message = null;
            while ( ( message = extractMessage( reader ) ) != null )
            {
                messages.add( message );
            }
        }
        finally
        {
            reader.close();
        }

        return messages;
    }

    private Message extractMessage( BufferedReader reader )
        throws IOException, SAXException
    {
        String header = reader.readLine();
        if ( header == null )
        {
            return null;
        }

        Message message = new Message();
        reader.readLine(); // ---------------------------
        message.setId( extractMessageParameter( reader ) );
        if ( header.endsWith( "Inbound Message" ) )
        {
            message.setType( Message.Type.INBOUND );
        }
        else
        {
            message.setType( Message.Type.OUTBOUND );
            message.setAddress( extractMessageParameter( reader ) );
        }
        reader.readLine(); // Encoding:
        reader.readLine(); // Content-Type:
        message.setHeaders( extractMessageHeadersParameter( reader ) );
        message.setPayload( extractMessagePayload( reader ) );
        return message;
    }

    private String extractMessageParameter( BufferedReader reader )
        throws IOException
    {
        String line = reader.readLine();
        String[] splits = line.split( ": " );
        return splits.length == 2 ? splits[1] : null;
    }

    private Map<String, String> extractMessageHeadersParameter( BufferedReader reader )
        throws IOException
    {
        String headersParameter = extractMessageParameter( reader );
        headersParameter = headersParameter.replaceFirst( "^\\{(.*)\\}$", "$1" );
        String[] headers = headersParameter.split( ", " );

        Map<String, String> headersMap = new HashMap<String, String>();
        for ( String header : headers )
        {
            String key = header.replaceFirst( "^(.*)=\\[.*\\]$", "$1" );
            String value = header.replaceFirst( "^.*=\\[(.*)\\]$", "$1" );
            headersMap.put( key, value );
        }
        return headersMap;
    }

    private Document extractMessagePayload( BufferedReader reader )
        throws IOException, SAXException
    {

        String line = extractMessageParameter( reader );
        boolean valid = line != null;

        StringBuffer buffer = new StringBuffer( StringUtils.trimToEmpty( line ) );
        while ( !( line = reader.readLine() ).equals( "--------------------------------------" ) )
        {
            buffer.append( line );
        }
        return valid ? builder.parse( new ByteArrayInputStream( buffer.toString().getBytes() ) ) : null;
    }
}
